/* eslint-disable */

(function() {
  const OldDate = Date
  // 重写arguments[0]
  Date = function () {
    if (arguments.length > 0 && typeof (arguments[0]) === 'string' && arguments[0].includes('-')) {
      const p = arguments[0].replace(/-/g, '/')
      arguments[0] = p
    }
    if (arguments.length === 1 && !arguments[0]) {
      return new OldDate()
    }
    return new OldDate(...arguments)
  }
  // 继承原型函数
  Date.prototype = OldDate.prototype
  // 继承静态函数，过滤已有的静态函数和参数，取数组差集
  const oldDateStaticParam = Object.getOwnPropertyNames(OldDate)
  const dateStaticParam = Object.getOwnPropertyNames(Date)
  const diffParam = []
  for (let i = 0; i < oldDateStaticParam.length; i++) {
    let find = false
    for (let j = 0; j < dateStaticParam.length; j++) {
      if (oldDateStaticParam[i] === dateStaticParam[j]) {
        find = true
        break
      }
    }
    if (!find) {
      diffParam.push(oldDateStaticParam[i])
    }
  }
  for (let i = 0; i < diffParam.length; i++) {
    Date[diffParam[i]] = OldDate[diffParam[i]]
  }

})()

Date.prototype.Format = function(format) {
  format = format || 'yyyy-MM-dd hh:mm:ss'
  var o = {
    'M+': this.getMonth() + 1, // month
    'd+': this.getDate(), // day
    'h+': this.getHours(), // hour
    'm+': this.getMinutes(), // minute
    's+': this.getSeconds(), // second
    'q+': Math.floor((this.getMonth() + 3) / 3), // quarter
    S: this.getMilliseconds() // millisecond
  };
  var week = ['日', '一', '二', '三', '四', '五', '六'];
  if (/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
  }
  if (/(w+)/.test(format)) {
    format = format.replace(RegExp.$1, week[this.getDay()]);
  }
  for (var k in o) {
    if (new RegExp('(' + k + ')').test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
    }
  }
  return format;
};

export function timeFormat(time, format = 'yyyy-MM-dd hh:mm:ss') {
  if (!time) return ''
  let date = new Date(time)
  return date.Format(format)
}

/**
 * @param {number} time
 * @returns {string}
 */
export function calcTime(time = 0) {
  time = +time
  let m = time % 60
  let th = time / 60 | 0
  let h = th % 24
  let d = th / 24 | 0
  return `${d?`${d}天`:''}${th?`${h}时`:''}${m}分`
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function getQueryObject(url = null) {
  url = url == null ? window.location.href : url
  const search = url.substring(url.lastIndexOf('?') + 1)
  const obj = {}
  const reg = /([^?&=]+)=([^?&=]*)/g
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1)
    let val = decodeURIComponent($2)
    val = String(val)
    obj[name] = val
    return rs
  })
  return obj
}

// 获取地址栏参数
export function getQueryString(name) {
  return getQueryObject()[name]
}

/**
 * @param {string} input value
 * @returns {number} output value
 */
export function byteLength(str) {
  // returns the byte length of an utf8 string
  let s = str.length
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i)
    if (code > 0x7f && code <= 0x7ff) s++
    else if (code > 0x7ff && code <= 0xffff) s += 2
    if (code >= 0xDC00 && code <= 0xDFFF) i--
  }
  return s
}

/**
 * @param {Array} actual
 * @returns {Array}
 */
export function cleanArray(actual) {
  const newArray = []
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i])
    }
  }
  return newArray
}

/**
 * @param {Object} json
 * @returns {Array}
 */
export function param(json) {
  if (!json) return ''
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return ''
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
    })
  ).join('&')
}

/**
* 参数处理
* @param {*} params  参数
*/
export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    var part = encodeURIComponent(propName) + "=";
    if (value !== null && value !== "" && typeof (value) !== "undefined") {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
            let params = propName + '[' + key + ']';
            var subPart = encodeURIComponent(params) + "=";
            result += subPart + encodeURIComponent(value[key]) + "&";
          }
        }
      } else {
        result += part + encodeURIComponent(value) + "&";
      }
    }
  }
  return result
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
  if (!search) {
    return {}
  }
  const obj = {}
  const searchArr = search.split('&')
  searchArr.forEach(v => {
    const index = v.indexOf('=')
    if (index !== -1) {
      const name = v.substring(0, index)
      const val = v.substring(index + 1, v.length)
      obj[name] = val
    }
  })
  return obj
}
/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text(val) {
  const div = document.createElement('div')
  div.innerHTML = val
  return div.textContent || div.innerText
}

/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge(target, source) {
  if (typeof target !== 'object') {
    target = {}
  }
  if (Array.isArray(source)) {
    return source.slice()
  }
  Object.keys(source).forEach(property => {
    const sourceProperty = source[property]
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty)
    } else {
      target[property] = sourceProperty
    }
  })
  return target
}

/**
 * @param {HTMLElement} element
 * @param {string} className
 */
export function toggleClass(element, className) {
  if (!element || !className) {
    return
  }
  let classString = element.className
  const nameIndex = classString.indexOf(className)
  if (nameIndex === -1) {
    classString += '' + className
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length)
  }
  element.className = classString
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function() {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone(source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'deepClone')
  }
  const targetObj = source.constructor === Array ? [] : {}
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys])
    } else {
      targetObj[keys] = source[keys]
    }
  })
  return targetObj
}

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr(arr) {
  return Array.from(new Set(arr))
}

/**
 * @returns {string}
 */
export function createUniqueString() {
  const timestamp = +new Date() + ''
  const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  return (+(randomNum + timestamp)).toString(32)
}

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
    ele.className = ele.className.replace(reg, ' ')
  }
}

export function makeMap(str, expectsLowerCase) {
  const map = Object.create(null)
  const list = str.split(',')
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true
  }
  return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]
}

// 表单重置
export function resetForm(refName) {
  if (this.$refs[refName]) {
    this.$refs[refName].resetFields();
  }
}
 
// 日期格式化
export function dateFormats(date, pattern) {
  let d = new Date(date).Format("yyyy-MM-dd hh:mm:ss");
  if (pattern) {
    d = new Date(date).Format(pattern);
  }
  return d.toLocaleString();
}
// 首字母大小
export function titleCase(str) {
  return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
}

// 下划转驼峰
export function camelCase(str) {
  return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase())
}

export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}


/**
 * iframe 下载
 * @param {*} url 
 */
export function iframeDownload(url, data) {
  const query = param(data)
  if (query) {
    url = url + '?' + query
  }
  const iframe = document.createElement('iframe')
  iframe.style.display = 'none'
  let loading = false

  function iframeLoad() {
    const win = iframe.contentWindow
    const doc = win.document
    if (win.location.href === url) {
      if (doc.body.childNodes.length > 0) {
        // response is error
      }
      iframe.parentNode.removeChild(iframe)
    } else {
      if (loading) {
        loading = false
        // Message.error('下载失败')
      }
    }
  }
  if ('onload' in iframe) {
    iframe.onload = iframeLoad
  } else if (iframe.attachEvent) {
    iframe.attachEvent('onload', iframeLoad)
  } else {
    iframe.onreadystatechange = function onreadystatechange() {
      if (iframe.readyState === 'complete') {
        iframeLoad
      }
    }
  }
  iframe.src = ''
  document.body.appendChild(iframe)

  setTimeout(function loadUrl() {
    loading = true
    iframe.contentWindow.location.href = url
  }, 50)
}


// excel导入数据格式转换
export function file2Xce(file) {
  let wb = null;
  return new Promise(function (resolve, reject) {
    const reader = new FileReader()
    reader.onload = function (e) {
      const data = e.target.result
      wb = XLSX.read(data, {
        type: 'binary'
      })
      const result = []
      wb.SheetNames.forEach((sheetName) => {
        result.push({
          sheetName: sheetName,
          sheet: XLSX.utils.sheet_to_json(wb.Sheets[sheetName])
        })
      })
      resolve(result)
    }
    reader.readAsBinaryString(file)
  })
}
// 导出xlsx
export function s2ab(s) {
  if (typeof ArrayBuffer !== 'undefined') {
    let buf = new ArrayBuffer(s.length);
    let view = new Uint8Array(buf);
    for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
    return buf;
  } else {
    let buf = new Array(s.length);
    for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
    return buf;
  }
}
export function saveAs(obj, fileName) {
  let tmpa = document.createElement("a");
  tmpa.download = fileName || "下载";
  tmpa.href = URL.createObjectURL(obj);
  tmpa.click();
  setTimeout(function () {
    URL.revokeObjectURL(obj);
  }, 100);
}
export function downloadExl(wb, fileName) {
  let wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true };
  let type = wopts.bookType
  let tmpDown = new Blob([s2ab(XLSX.write(wb, { bookType: (type == undefined ? 'xlsx' : type), bookSST: false, type: 'binary' }))], { type: "" });
  saveAs(tmpDown, fileName + '.' + (wopts.bookType == "biff2" ? "xls" : wopts.bookType));
}
/**
 * 文件流砖base64
 * @param {*} file 
 */
export function readImg(file) {
  return new Promise((res) => {
    // 创建一个reader
    const reader = new FileReader()
    // 将图片2将转成 base64 格式
    reader.readAsDataURL(file)
    // 读取成功后的回调
    reader.onloadend = function() {
      // console.log(this.result);
      const result = this.result
      res(result)
    }
  })
}

// 下载图片/文本 禁止打开 -- blob
export function downloadBlob(url, name="download") {
  function toDataURL(url) {
      return fetch(url).then((response) => {
              return response.blob();
          }).then(blob => {
              return URL.createObjectURL(blob);
          });
  }
  (async function() {
      const a = document.createElement("a");
      imgUrl = url+'?'+Math.random()
      a.href = await toDataURL(imgUrl);
      a.setAttribute('download', name)
      a.click();
  })()
}

// 下载图片/文本 禁止打开 -- XMLHttpRequest
export function downloadFetch(url, name="download") {
  var x = new XMLHttpRequest();
  x.open("GET", url, true);
  x.responseType = 'blob';
  x.onload = function (e) {
    var url = window.URL.createObjectURL(x.response)
    var a = document.createElement('a');
    a.href = url
    a.download = name
    a.click()
  }
  x.send();
}

// 图片连接添加时间戳，防止缓存
export function imgUrlAddTime(url) {
  if (/^(http|https):\/\/.+$/.test(url)) {
    return url + '?t=' + new Date().getTime()
  }
  return url
}

/**
 * @desc 函数节流
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param type 1 表时间戳版，2 表定时器版
 */
export function throttle(func, wait, type) {
  wait = wait || 100
  type = type || 1
  let previous = 0;
  let timeout;
  return function () {
    const context = this;
    const args = arguments;
    if (type === 1) {
      const now = Date.now();

      if (now - previous > wait) {
        func.apply(context, args);
        previous = now;
      }
    } else if (type === 2) {
      if (!timeout) {
        timeout = setTimeout(() => {
          timeout = null;
          func.apply(context, args)
        }, wait)
      }
    }
  }
}

/**
 * 数字转中文
 * @param {Number} num 
 * @returns {string}
 */
 export function NoToChinese(num) {
  if (!/^\d*(\.\d*)?$/.test(num)) {
      return "";
  }
  var AA = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
  var BB = new Array("", "十", "百", "千", "万", "亿", "点", "");
  var a = ("" + num).replace(/(^0*)/g, "").split("."),
      k = 0,
      re = "";
  var round = a[0] // 整数部分
  for (var i = round.length - 1; i >= 0; i--) {
      switch (k) {
          case 0:
              re = BB[7] + re;
              break;
          case 4:
              if (!new RegExp("0{4}\\d{" + (round.length - i - 1) + "}$").test(round))
                  re = BB[4] + re;
              break;
          case 8:
              re = BB[5] + re;
              BB[7] = BB[5];
              k = 0;
              break;
      }
      if (k % 4 == 2 && round.charAt(i + 2) != 0 && round.charAt(i + 1) == 0) {
        re = AA[0] + re;
      }
      if (round.charAt(i) != 0) {
        if (round < 20 && round > 9 && i === 0) { // 10-19 特殊处理
          re = BB[k % 4] + re;
        } else {
          re = AA[round.charAt(i)] + BB[k % 4] + re;
        }
        
      }
      k++;
  }
  if (a.length > 1) { //加上小数部分(如果有小数部分)
      re += BB[6];
      for (var i = 0; i < a[1].length; i++) re += AA[a[1].charAt(i)];
  }
  return re;
};

// 字符串转base64
export function stringToBase64(str) {
  str = str + '';
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
    return String.fromCharCode('0x' + p1);
  }));
}
